import logging
import allure
from utils.get_keywords import GetKeywords
from utils.send_request import send_jdbc_request
from utils.regex import *


class Extractor:
    """抽象提取器类，定义了提取数据的基本方法"""

    def __init__(self, case, all_vars):
        """所有方法都要传入的参数"""
        self.case = case
        self.all_vars = all_vars

    def extract(self, res=None):
        """子类需要去实现的方法"""
        raise NotImplementedError("子类必须实现extract方法")

    def log_extraction(self, extraction_type, data):
        """日志需要去打印的内容"""
        logging.info(f"4.{extraction_type}, 根据{data}提取数据, 此时全局变量为: {self.all_vars}")

    def add_to_all_vars(self, key, value):
        """存入全局变量的方法"""
        self.all_vars[key] = value

    def eval_data(self, data_str):
        """eval的封装方法"""
        return eval(data_str) if data_str else None


class JsonExtractor(Extractor):

    @allure.step("4.JSON提取")
    def extract(self, res):
        if self.case["jsonExData"]:
            # 首先要把 jsonExData 的 key, value 拆开
            for key, value in self.eval_data(self.case["jsonExData"]).items():
                value = GetKeywords.get_keyword(res, value)
                self.add_to_all_vars(key, value)
            self.log_extraction("JSON提取", self.case["jsonExData"])


class JDBCExtractor(Extractor):

    @allure.step("4.JDBC提取")
    def extract(self):
        if self.case["sqlExData"]:
            for key, value in self.eval_data(self.case["sqlExData"]).items():
                value = send_jdbc_request(value)
                self.add_to_all_vars(key, value)
            self.log_extraction("JDBC提取", self.case["sqlExData"])


class ReExtractor(Extractor):

    @allure.step("4.正则提取")
    def extract(self, res):
        """
        提取值的方法
        :param case: 用例数据
        :param all: 全局变量
        :param res: 返回值
        :return:
        """
        if self.case['reExData']:
            for key, value in self.eval_data(self.case["reExData"]).items():
                value = extract_matches_with_positions(str(res), value)
                self.add_to_all_vars(key, value)
            self.log_extraction("正则提取", self.case['reExData'])


def perform_extractions(case, all_vars, response):
    """
    执行提取器，执行的入口
    :param case:
    :param all_vars:
    :param response:
    :return:
    """

    extractors = [
        JsonExtractor(case, all_vars),
        JDBCExtractor(case, all_vars),
        ReExtractor(case, all_vars)
    ]

    for extractor in extractors:
        try:
            if isinstance(extractor, JsonExtractor) or isinstance(extractor, ReExtractor):
                extractor.extract(response)
            elif isinstance(extractor, JDBCExtractor):
                extractor.extract()
        except Exception as e:
            logging.error(f"在执行 {type(extractor).__name__} 时发生错误: {e}")



